/**
 * 
 */
package cn.edu.ustc.multicore.exercise.ch5;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author dragon
 * 
 */
public class SimpleReadWriteLock implements ReadWriteLock {

	int readers;
	boolean writer;
	Lock lock;
	Condition condition;
	Lock readLock, writeLock;

	public SimpleReadWriteLock() {
		writer = false;
		readers = 0;
		lock = new ReentrantLock();
		readLock = new ReadLock();
		writeLock = new WriteLock();
		condition = lock.newCondition();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.util.concurrent.locks.ReadWriteLock#readLock()
	 */
	public Lock readLock() {
		return this.readLock;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.util.concurrent.locks.ReadWriteLock#writeLock()
	 */
	public Lock writeLock() {
		return this.writeLock;
	}

	private class ReadLock implements Lock {

		public void lock() {
			lock.lock();
			try {
				while (writer) {
					condition.await();
				}
				readers++;
			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally {
				lock.unlock();
			}
		}

		public void unlock() {
			lock.lock();
			try {
				readers--;
				if (readers == 0)
					condition.signalAll();
			} finally {
				lock.unlock();
			}
		}

		public void lockInterruptibly() throws InterruptedException {
			// TODO Auto-generated method stub

		}

		public Condition newCondition() {
			// TODO Auto-generated method stub
			return null;
		}

		public boolean tryLock() {
			// TODO Auto-generated method stub
			return false;
		}

		public boolean tryLock(long time, TimeUnit unit)
				throws InterruptedException {
			// TODO Auto-generated method stub
			return false;
		}
	}

	private class WriteLock implements Lock {

		public void lock() {
			lock.lock();
			try {
				while (readers > 0) {
					condition.await();
				}
				writer = true;
			} catch (InterruptedException e) {
				e.printStackTrace();
			}finally{
				lock.unlock();
			}
		}

		public void unlock() {
			
			lock.lock();
			try {
				writer = false;
				condition.signalAll();
			} finally {
				lock.unlock();
			}
		}

		public void lockInterruptibly() throws InterruptedException {

		}

		public Condition newCondition() {
			// TODO Auto-generated method stub
			return null;
		}

		public boolean tryLock() {
			// TODO Auto-generated method stub
			return false;
		}

		public boolean tryLock(long time, TimeUnit unit)
				throws InterruptedException {
			// TODO Auto-generated method stub
			return false;
		}

	}

}
